/********************************************************************************************/
/* Fullhan Technology (Shanghai) Co., Ltd.                                                  */
/* Fullhan Proprietary and Confidential                                                     */
/* Copyright (c) 2014 Fullhan Technology Group Limited and its affiliated companies         */
/********************************************************************************************/

#ifndef _DES_A_H_
#define _DES_A_H_ 1
#if 0
#ifndef _MSC_VER
#define _MSC_VER
#if defined(_MSC_VER)
	/**
	 * \name ISO C99 fixed-size types
	 *
	 * These should be in <stdint.h>, but a few compilers lack them.
	 * \{
	 */
	typedef signed char         int8_t;
	typedef unsigned char       uint8_t;
	typedef short int           int16_t;
	typedef unsigned short int  uint16_t;
//	typedef long int            int32_t; /* _WIN64 safe */
	typedef unsigned long int   uint32_t; /* _WIN64 safe */
	typedef unsigned int		size_t;
#if 0
	#ifdef _MSC_VER
		typedef __int64              int64_t;
		typedef unsigned __int64     uint64_t;
	#else
		typedef long long            int64_t;
		typedef unsigned long long   uint64_t;
	#endif
#else 
		typedef long long            int64_t;
		typedef unsigned long long   uint64_t;
#endif
	/* \} */
#else
	/* This is the standard location. */
	#include <stdint.h>
#endif
#endif
#else
	#include <stdint.h>
	typedef unsigned int		size_t;
#endif

#define PURGE(x) \
	memset(&x, 0, sizeof(x))

#define IS_LITTLE_ENDIAN

typedef unsigned int  HALF;

#define HALFPTR(x) ((HALF *)(x))
#define SHORTPTR(x) ((unsigned short *)(x))
#define BYTEPTR(x) ((BYTE *)(x))

typedef enum {
    DES_ENCRYPT = 0x5555,
    DES_DECRYPT = 0xAAAA
} DESDirection;


typedef struct DESBlockCipher
{
	void (*set_key)(struct DESBlockCipher *c, const void *key1, const void *key2, const void *key3, DESDirection direction);
	void (*enc_block)(struct DESBlockCipher *c, void *block);
	void (*dec_block)(struct DESBlockCipher *c, void *block);
	void *buf;
	uint8_t block_len;
} DESBlockCipher;

typedef struct
{
	DESBlockCipher c;
	HALF key1[8];
	HALF key2[8];
	HALF key3[8];
	HALF exkey1[32];
	HALF exkey2[32];
	HALF exkey3[32];
} DES_Context;


void DES_Init(DES_Context *p_des_ctx);
void TDES_Init(DES_Context *p_des_ctx);

void des_cipher_ecb_encrypt(DESBlockCipher *c, void *block);
void des_cipher_ecb_decrypt(DESBlockCipher *c, void *block);
void des_cipher_cbc_encrypt(DESBlockCipher *c, void *block);
void des_cipher_cbc_decrypt(DESBlockCipher *c, void *block);
void des_cipher_ctr_encrypt(DESBlockCipher *c, void *block);
void des_cipher_ctr_decrypt(DESBlockCipher *c, void *block);
void des_cipher_ofb_encrypt(DESBlockCipher *c, void *block);
void des_cipher_ofb_decrypt(DESBlockCipher *c, void *block);
void des_cipher_cfb1_encrypt(DESBlockCipher *c, void *block);
void des_cipher_cfb1_decrypt(DESBlockCipher *c, void *block);
void des_cipher_cfb8_encrypt(DESBlockCipher *c, void *block);
void des_cipher_cfb8_decrypt(DESBlockCipher *c, void *block);
void des_cipher_cfb64_encrypt(DESBlockCipher *c, void *block);
void des_cipher_cfb64_decrypt(DESBlockCipher *c, void *block);
void des_cipher_ofb1_encrypt(DESBlockCipher *c, void *block);
void des_cipher_ofb1_decrypt(DESBlockCipher *c, void *block);
void des_cipher_ofb8_encrypt(DESBlockCipher *c, void *block);
void des_cipher_ofb8_decrypt(DESBlockCipher *c, void *block);
void des_cipher_ofb64_encrypt(DESBlockCipher *c, void *block);
void des_cipher_ofb64_decrypt(DESBlockCipher *c, void *block);

int is_aligned(const void *addr, size_t size);
void xor_block_8(uint8_t *out, const uint8_t *in1, const uint8_t *in2, size_t len);
void xor_block_const_8(uint8_t *out, const uint8_t *in, uint8_t k, size_t len);
void xor_block_32(uint32_t *out, const uint32_t *in1, const uint32_t *in2, size_t len);
void xor_block_const_32(uint32_t *out, const uint32_t *in, uint8_t k, size_t len);
void xor_block(void *out, const void *in1, const void *in2, size_t len);
void xor_block_const(uint8_t *out, const uint8_t *in, uint8_t k, size_t len);
void lshift_block(uint8_t *out, const uint8_t *in, uint8_t shift, size_t len);
void rshift_block(uint8_t *out, const uint8_t *in, uint8_t shift, size_t len);
void or_block(uint8_t *out, const uint8_t *in1, const uint8_t *in2, size_t len);
void and_block(uint8_t *out, const uint8_t *in1, const uint8_t *in2, size_t len);
void not_block(uint8_t *out, const uint8_t *in, size_t len);
#endif
